package com.itfenghuang.day12;

import java.util.concurrent.locks.ReentrantLock;

public class A01_ThreadSecurity {
    public static void main(String[] args) {
        /**
         *  1. 案列:
         *      卖票
         *      需求;某电影院正在上映大片,共有100张票,共有三个售票窗口
         *      请设计程序模拟电影院卖票
         *      分析:
         *          1). 定义一个类(Ticket) 实现Runnable接口 重写抽象方法
         *          定义一个成员变量: 总的票数 100张
         *          2). 卖票
         *                  循环卖票 while  使用if 判断 票数大于0 票数-1 ,else( 移出循环)
         *                  3个窗口  测试类创建3个线程对象, 开启线程卖票
         *      卖票出现的问题:
         *          1). 相同的票出现了多次
         *
         *  2. 使用同步技术解决线程安全问题
         *          线程安全问题出现条件:
         *              1). 多线程环境
         *              2). 有共享数据
         *              3). 有多条语句操作共享数据
         *
         *      解决线程安全问题
         *          让程序没有线程安全问题
         *
         *     同步代码块
         *      synchronize(锁对象){
         *
         *      }
         *      如果想要使用同步技术解决线程安全问题
         *          1). 锁对象要唯一  private Object obj=new Object();
         *
         *  同步技术的优缺点:
         *      解决了在多线程中数据安全问题
         *      当线程很多的时候,每个线程都会去判断同步上的锁,很耗费资源,无形中降低程序的执行效率
         *
         *  同步方法
         *   格式:  访问修饰符 synchronized 返回值类型 方法名(方法参数){方法体}
         *   解决步骤;
         *      1). 将访问共享数据的代码块抽取出来,放到了一个方法中
         *      2). 在方法上加了一个关键字synchronized
         *      同步方法中的锁对象是哪个对象
         *      this
         *
         *      Thread类 sleep不会释放锁 可以在任意地方调用
         *      objec类 wait 释放锁   同步代码块和同步方法使用
         *
         *
         */
        Ticket ticket = new Ticket();
        //创建Thread类
        Thread thread1 = new Thread(ticket,"窗口一");
        Thread thread2 = new Thread(ticket,"窗口二");
        Thread thread3 = new Thread(ticket,"窗口三");
        //开启线程
        thread1.start();
        thread2.start();
        thread3.start();

    }
}
//卖票问题
//同步代码块 或者 同步方法
class Ticket implements Runnable{
    private int ticketTotal=100;
    //同步代码块加锁对象
    private Object obj=new Object();


    @Override
    public void run() {
        while (true){
            synchronized (obj){
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //判断票数是否大于0
                if (ticketTotal>0){
                    //获取线程名字
                    System.out.println(Thread.currentThread().getName()+"卖出了第"+ticketTotal+"张票");
                    ticketTotal--;
                }else {
                    break;
                }
            }
        }
    }

//    @Override
//    public void run() {
//        while (true){
//            method();
//            if (ticketTotal<=0){
//                break;
//            }
//        }
//    }
//    private synchronized void method() {
//        //判断票数是否大于0
//        if (ticketTotal>0){
//            //获取线程名字
//            System.out.println(Thread.currentThread().getName()+"卖出了第"+ticketTotal+"张票");
//            ticketTotal--;
//        }
//    }
}
